{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "source": [
        "# (1) Install dependencies"
      ],
      "metadata": {
        "id": "C-68gn27DW8M"
      }
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "rAn9fYboCwEL"
      },
      "outputs": [],
      "source": [
        "!apt update\n",
        "!apt-get install libdw-dev"
      ]
    },
    {
      "cell_type": "markdown",
      "source": [],
      "metadata": {
        "id": "ug98NmwFOnzG"
      }
    },
    {
      "cell_type": "markdown",
      "source": [
        "#(1) Download the BMF Release library and extract it to the local environment"
      ],
      "metadata": {
        "id": "ISczRD0avf5M"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "!pip install BabitMF"
      ],
      "metadata": {
        "id": "07aSAmV1OUG_"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "source": [
        "#(3) Configure the environment variable to reference the BMF C library"
      ],
      "metadata": {
        "id": "RReEQfMkvtxP"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "!bmf_env"
      ],
      "metadata": {
        "id": "XwnRT5RROsJz"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "%env C_INCLUDE_PATH=/usr/local/lib/python3.10/dist-packages/bmf/include\n",
        "%env CPLUS_INCLUDE_PATH=/usr/local/lib/python3.10/dist-packages/bmf/include\n",
        "%env LIBRARY_PATH=/usr/local/cuda/lib64/stubs:/usr/local/lib/python3.10/dist-packages/bmf/lib\n",
        "%env LD_LIBRARY_PATH=/usr/local/nvidia/lib:/usr/local/nvidia/lib64:/usr/local/lib/python3.10/dist-packages/bmf/lib"
      ],
      "metadata": {
        "id": "SbOt_Q1KqP7G"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "!echo $LD_LIBRARY_PATH"
      ],
      "metadata": {
        "id": "-3VGuihKP4B4"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "!wget https://github.com/BabitMF/bmf/releases/download/files/files.tar.gz\n",
        "!tar -zvxf files.tar.gz"
      ],
      "metadata": {
        "id": "sxrMv1I2te_I"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "%%writefile /content/sync_mode.cpp\n",
        "#include \"builder.hpp\"\n",
        "#include \"nlohmann/json.hpp\"\n",
        "\n",
        "\n",
        "int main()\n",
        "{\n",
        "    std::string output_file = \"./sync_mode.mp4\";\n",
        "\n",
        "    bmf::builder::Graph graph = bmf::builder::Graph(bmf::builder::NormalMode);\n",
        "\n",
        "    // create sync modules\n",
        "    nlohmann::json decoder_option = {\n",
        "        {\"input_path\", \"./files/big_bunny_10s_30fps.mp4\"}\n",
        "    };\n",
        "    auto decoder = graph.Sync(std::vector<int> {}, std::vector<int> {0,1}, decoder_option, \"c_ffmpeg_decoder\");\n",
        "\n",
        "    nlohmann::json scale_option = {\n",
        "        {\"name\", \"scale\"},\n",
        "        {\"para\", \"320:250\"}\n",
        "    };\n",
        "    auto scale = graph.Sync(std::vector<int> {0}, std::vector<int> {0},\n",
        "        bmf_sdk::JsonParam(scale_option), \"c_ffmpeg_filter\");\n",
        "\n",
        "    nlohmann::json volume_option = {\n",
        "        {\"name\", \"volume\"},\n",
        "        {\"para\", \"volume=3\"}\n",
        "    };\n",
        "    auto volume = graph.Sync(std::vector<int> {0}, std::vector<int> {0}, volume_option, \"c_ffmpeg_filter\");\n",
        "\n",
        "    nlohmann::json encoder_option = {\n",
        "        {\"output_path\", output_file}\n",
        "    };\n",
        "    auto encoder = graph.Sync(std::vector<int> {0,1}, std::vector<int> {}, encoder_option, \"c_ffmpeg_encoder\");\n",
        "\n",
        "    // call init if necessary, otherwise we skip this step\n",
        "    graph.Init(decoder);\n",
        "    graph.Init(scale);\n",
        "    graph.Init(volume);\n",
        "    graph.Init(encoder);\n",
        "\n",
        "    // process video/audio by sync mode\n",
        "    while (1) {\n",
        "        auto decoded_frames = graph.Process(decoder, bmf::builder::SyncPackets());\n",
        "        bool has_next = false;\n",
        "        for (const auto &stream : decoded_frames.packets) {\n",
        "            if (!stream.second.empty()) {\n",
        "                has_next = true;\n",
        "                if (stream.first == 0) {\n",
        "                    bmf::builder::SyncPackets input_scale;\n",
        "                    input_scale.Insert(0, decoded_frames[0]);\n",
        "                    auto scaled_frames = graph.Process(scale, input_scale);\n",
        "\n",
        "                    bmf::builder::SyncPackets input_encoder;\n",
        "                    input_encoder.Insert(0, scaled_frames[0]);\n",
        "                    graph.Process(encoder, input_encoder);\n",
        "                    //encoder.ProcessPkts(input_encoder);\n",
        "                } else if (stream.first == 1) {\n",
        "                    bmf::builder::SyncPackets input_volume;\n",
        "                    input_volume.Insert(0, decoded_frames[1]);\n",
        "                    auto volume_frames = graph.Process(volume, input_volume);\n",
        "                    //auto volume_frames = volume.ProcessPkts(input_volume);\n",
        "\n",
        "                    bmf::builder::SyncPackets input_encoder;\n",
        "                    input_encoder.Insert(1, volume_frames[0]);\n",
        "                    graph.Process(encoder, input_encoder);\n",
        "                    //encoder.ProcessPkts(input_encoder);\n",
        "                }\n",
        "            }\n",
        "        }\n",
        "        if (!has_next) {\n",
        "            break;\n",
        "        }\n",
        "    }\n",
        "\n",
        "    // call close if necessary, otherwise we skip this step\n",
        "    graph.Close(decoder);\n",
        "    graph.Close(scale);\n",
        "    graph.Close(volume);\n",
        "    graph.Close(encoder);\n",
        "\n",
        "}\n"
      ],
      "metadata": {
        "id": "J0AW-t-FdqTq"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "%%writefile /content/CMakeLists.txt\n",
        "file(GLOB SRCS *.cpp *.h)\n",
        "add_library(nlohmann INTERFACE IMPORTED GLOBAL)\n",
        "add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)\n",
        "add_executable(sync_mode ${SRCS})\n",
        "\n",
        "target_link_libraries(\n",
        "    sync_mode\n",
        "    PRIVATE\n",
        "    bmf_module_sdk hmp engine nlohmann\n",
        ")"
      ],
      "metadata": {
        "id": "w_l4FVJ7kISe"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "!rm -rf CMakeCache.txt CMakeFiles cmake_install.cmake Makefile"
      ],
      "metadata": {
        "id": "5spkUpJ1ZRc2"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "!cmake .\n",
        "!make"
      ],
      "metadata": {
        "id": "fentyJzMl2WS"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "!./sync_mode"
      ],
      "metadata": {
        "id": "2d4Eb-AAn9nQ"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "from IPython.display import HTML\n",
        "from base64 import b64encode\n",
        "\n",
        "def show_video(video_path, video_width = 800):\n",
        "  video_file = open(video_path, \"r+b\").read()\n",
        "  video_url = f\"data:video/mp4;base64,{b64encode(video_file).decode()}\"\n",
        "  return f\"\"\"\n",
        "  <video width={video_width} controls>\n",
        "    <source src=\"{video_url}\">\n",
        "  </video>\n",
        "  \"\"\"\n",
        "\n",
        "video_url1 = show_video('./files/big_bunny_10s_30fps.mp4')\n",
        "video_url2 = show_video('sync_mode.mp4')\n",
        "\n",
        "html = video_url1 + video_url2\n",
        "HTML(html)"
      ],
      "metadata": {
        "id": "OoQkamtnj9uy"
      },
      "execution_count": null,
      "outputs": []
    }
  ]
}
